package cn.tb.ymcc.service.impl;

import cn.tb.ymcc.constants.CommonConstants;
import cn.tb.ymcc.domain.*;
import cn.tb.ymcc.dto.RedisRegisterDto;
import cn.tb.ymcc.dto.RegisterDto;
import cn.tb.ymcc.feign.LoginFeignClient;
import cn.tb.ymcc.mapper.UserMapper;
import cn.tb.ymcc.result.JSONResult;
import cn.tb.ymcc.service.IUserAccountService;
import cn.tb.ymcc.service.IUserBaseInfoService;
import cn.tb.ymcc.service.IUserReferralcodeService;
import cn.tb.ymcc.service.IUserService;
import cn.tb.ymcc.util.AssertUtil;
import cn.tb.ymcc.util.VerifyCodeUtils;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author tangbo
 * @since 2022-07-15
 */
@Service

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private LoginFeignClient loginFeignClient;
    @Autowired
    private IUserAccountService userAccountService;
    @Autowired
    private IUserBaseInfoService userBaseInfoService;
    @Autowired
    private IUserReferralcodeService userReferralcodeService;


    /**
     * 1.参数校验
     * 2.验证码是否正确
     * 3.手机号不能被注册
     *
     * ==保存
     *  保存t_login
     *    。在service-uaa编写controller接口，调用service保存t_login数据
     *    。为service-uaa的controller编写Feign，给service-user调用
     *
     *  保存user相关
     *    调用对应的service保存数据即可 t_user  t_user_base_info  t_user_account
     * @param dto
     */
    @Override
    @GlobalTransactional
    public void register(RegisterDto dto) {
        String key = String.format(CommonConstants.REGISTER_PHONE_PRIFIX,dto.getMobile());
        Object o = redisTemplate.opsForValue().get(key);
        AssertUtil.isNotNull(o,"验证码已经过期");
        //判断手机验证码是否正确
        RedisRegisterDto redisRegisterDto = (RedisRegisterDto) o;
        AssertUtil.isEqualsIgnoreCase(redisRegisterDto.getCode(),dto.getSmsCode(),"验证码不正确");

        User user = userMapper.loadByMobile(dto.getMobile());
        AssertUtil.isNull(user,"用户已经存在");
        //保存t_login
        JSONResult result = saveLogin(dto);
        AssertUtil.isTrue(result.isSuccess(),result.getMessage());
        //login保存成功
        AssertUtil.isNotNull(result.getData(),"登录信息保存失败！");
        //保存user
        Long loginId = Long.valueOf(result.getData().toString());
        user = saveUser(loginId,dto.getMobile());
        //保存userBaseInfo
        initUserInfo(user.getId(),dto.getRegChannel());
        //保存userAccount
        initUserAccount(user.getId());
        
        //生成推荐码并且保存
        String code = VerifyCodeUtils.generateVerifyCode(4);
        saveReferralcode(user.getId(), code);
    }

    private UserReferralcode saveReferralcode(Long id,String code) {
        UserReferralcode userReferralcode = new UserReferralcode();
        userReferralcode.setUserId(id);
        userReferralcode.setCode(code);
        userReferralcodeService.insert(userReferralcode);
        return userReferralcode;
    }

    private void initUserAccount(Long userId) {
        UserAccount account = new UserAccount();
        account.setId(userId);
        account.setCreateTime(new Date().getTime());
        userAccountService.insert(account);
    }

    private void initUserInfo(Long userId,Integer regChannel) {
        UserBaseInfo info = new UserBaseInfo();
        info.setId(userId);
        info.setCreateTime(new Date().getTime());
        info.setRegChannel(regChannel);//注册渠道
        userBaseInfoService.insert(info);
    }
    private User saveUser(Long loginId,String mobile) {
        User user = new User();
        user.setLoginId(loginId);
        user.setPhone(mobile);
        user.setNickName(mobile);
        user.setCreateTime(new Date().getTime());
        insert(user);
        return user;
    }

    private JSONResult saveLogin(RegisterDto dto) {
        Login login = new Login();
        login.setUsername(dto.getMobile());
        login.setPassword(dto.getPassword());
        login.setType(Login.TYPE_USER);
        return loginFeignClient.save(login);
    }
}
